package com.tanqidi.arcgisandroid.ui.attachment

import android.content.Intent
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.lifecycle.viewModelScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.SimpleItemAnimator
import com.bm.library.PhotoView
import com.esri.arcgisruntime.data.ArcGISFeature
import com.esri.arcgisruntime.data.Attachment
import com.esri.arcgisruntime.data.GeodatabaseFeatureTable
import com.esri.arcgisruntime.data.ServiceFeatureTable
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.luck.picture.lib.animators.AnimationType
import com.luck.picture.lib.basic.PictureSelectionModel
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.PictureConfig
import com.luck.picture.lib.config.PictureMimeType
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.decoration.GridSpacingItemDecoration
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnExternalPreviewEventListener
import com.luck.picture.lib.interfaces.OnResultCallbackListener
import com.luck.picture.lib.style.PictureSelectorStyle
import com.luck.picture.lib.utils.DensityUtil
import com.luck.picture.lib.utils.MediaUtils
import com.luck.picture.lib.utils.PictureFileUtils
import com.qmuiteam.qmui.util.QMUIDisplayHelper
import com.tanqidi.arcgisandroid.R
import com.tanqidi.arcgisandroid.base.BaseRecyclerAdapter
import com.tanqidi.arcgisandroid.base.RecyclerViewHolder
import com.tanqidi.arcgisandroid.base.utils.showToast
import com.tanqidi.arcgisandroid.databinding.ActivityAttachmentBinding
import com.tanqidi.arcgisandroid.ui.HomeFragment
import com.tanqidi.arcgisandroid.ui.attachment.adapter.GridImageAdapter
import io.reactivex.rxjava3.core.Single
import kotlinx.coroutines.launch
import java.io.File
import java.util.concurrent.CancellationException


class AttachmentActivity : AppCompatActivity() {

    private lateinit var binding: ActivityAttachmentBinding
    private lateinit var attachmentAdapter: AttachmentAdapter
    private lateinit var localMediaAdapter: LocalMediaAdapter
    private val dataList = mutableListOf<LocalMedia>()
    private val maxSelectNum = 9
    private val maxSelectVideoNum = 1
    private lateinit var imageEngine: GlideEngine
    private val TAG = "AttachmentActivity"
    private val ACTIVITY_RESULT = 1
    private val CALLBACK_RESULT = 2
    private val LAUNCHER_RESULT = 3
    private val resultMode = LAUNCHER_RESULT

    /**
     * 创建一个ActivityResultLauncher
     *
     * @return
     */
    private val launcherResult: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        val resultCode = result.resultCode
        if (resultCode == RESULT_OK) {
            val selectList = PictureSelector.obtainSelectorList(result.data)
            analyticalSelectResults(selectList)
        } else if (resultCode == RESULT_CANCELED) {
            Log.i(TAG, "onActivityResult PictureSelector Cancel")
        }
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityAttachmentBinding.inflate(layoutInflater)
        setContentView(binding.root)
        initTopBar()
        initViewEvent()
        initRecycleView()
    }

    private fun initRecycleView() {
        val recyclerView = binding.recyclerView
        val manager = FullyGridLayoutManager(this, 4, GridLayoutManager.VERTICAL, false)
        recyclerView.layoutManager = manager
        val itemAnimator = recyclerView.itemAnimator
        if (itemAnimator != null) {
            (itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
        }

        if(HomeFragment.updateFeature != null){
            val fetchAttachmentsAsync = (HomeFragment.updateFeature as ArcGISFeature).fetchAttachmentsAsync()
            fetchAttachmentsAsync.addDoneListener {
                val get = fetchAttachmentsAsync.get()
                attachmentAdapter = AttachmentAdapter(get)
                recyclerView.adapter = attachmentAdapter
            }
        } else {
            /**
             * 如果updateFeature是空，那就是这次选择图片是新增要素，但也有可能是新增要素的时候反复打开图片选择界面选择图片
             * 如果是新增要素，选择完图片是不会把选中的结果放到当前activity的，而是直接丢到了HomeFragment.localMediaList里面了
             * 反复打开和选择，都是最新的结果，保存要素了就把换个HomeFragment.localMediaList清空clear掉就可以了
             */
            localMediaAdapter = LocalMediaAdapter(HomeFragment.localMediaList)
            recyclerView.adapter = localMediaAdapter
        }

    }

    private fun reloadFeatureAttachmentListToAdapter(){
        val fetchAttachmentsAsync = (HomeFragment.updateFeature as ArcGISFeature).fetchAttachmentsAsync()
        fetchAttachmentsAsync.addDoneListener {
            val get = fetchAttachmentsAsync.get()
            attachmentAdapter.data = get
        }
    }

    private fun initViewEvent() {
        imageEngine = GlideEngine.createGlideEngine()
        binding.select.setOnClickListener {
            val selectionModel: PictureSelectionModel = PictureSelector.create(this@AttachmentActivity)
                    .openGallery(SelectMimeType.ofAll())
                    .setSelectorUIStyle(PictureSelectorStyle())
                    .setImageEngine(imageEngine)
                    .isWithSelectVideoImage(true)
                    .isAutoVideoPlay(true)
                    .isLoopAutoVideoPlay(true)
                    .isPreviewZoomEffect(true)
                    .isPreviewImage(true)
                    .isPreviewVideo(true)
                    .isPreviewAudio(true)
                    .setMaxSelectNum(maxSelectNum)
                    .setMaxVideoSelectNum(maxSelectVideoNum)
                    .setRecyclerAnimationMode(AnimationType.DEFAULT_ANIMATION)

            /**
             * 是新增要素，因为是直接从pictureSelect选择器得到的对象可以原样显示出来，如果是更新要素是attachment不是localMedia对象所以没法子在本地重现选中的效果
             */
            if(HomeFragment.updateFeature == null){
                selectionModel.setSelectedData(HomeFragment.localMediaList)
            }
            forSelectResult(selectionModel)
        }
    }

    private fun initTopBar() {
        binding.topAppBar.apply {
            setNavigationOnClickListener {
                finish()
            }
            setOnMenuItemClickListener {
                when(it.itemId) {
                    R.id.accept -> {
                        finish()
                    }
                }
                true
            }
        }
    }

    private fun forSelectResult(model: PictureSelectionModel) {
        when (resultMode) {
            ACTIVITY_RESULT -> model.forResult(PictureConfig.CHOOSE_REQUEST)
            CALLBACK_RESULT -> model.forResult(object : OnResultCallbackListener<LocalMedia> {
                override fun onResult(p0: java.util.ArrayList<LocalMedia>) {
                    analyticalSelectResults(p0)
                }

                override fun onCancel() {
                }

            })
            else -> model.forResult(launcherResult)
        }
    }


    /**
     * 处理选择结果
     *
     * @param result
     */
    private fun analyticalSelectResults(result: ArrayList<LocalMedia>) {
        for (media in result) {
            if (media.width == 0 || media.height == 0) {
                if (PictureMimeType.isHasImage(media.mimeType)) {
                    val imageExtraInfo = MediaUtils.getImageSize(this, media.path)
                    media.width = imageExtraInfo.width
                    media.height = imageExtraInfo.height
                } else if (PictureMimeType.isHasVideo(media.mimeType)) {
                    val videoExtraInfo = MediaUtils.getVideoSize(this, media.path)
                    media.width = videoExtraInfo.width
                    media.height = videoExtraInfo.height
                }
            }
            Log.i(TAG, "文件名: " + media.fileName)
            Log.i(TAG, "是否压缩:" + media.isCompressed)
            Log.i(TAG, "压缩:" + media.compressPath)
            Log.i(TAG, "初始路径:" + media.path)
            Log.i(TAG, "绝对路径:" + media.realPath)
            Log.i(TAG, "是否裁剪:" + media.isCut)
            Log.i(TAG, "裁剪路径:" + media.cutPath)
            Log.i(TAG, "是否开启原图:" + media.isOriginal)
            Log.i(TAG, "原图路径:" + media.originalPath)
            Log.i(TAG, "沙盒路径:" + media.sandboxPath)
            Log.i(TAG, "水印路径:" + media.watermarkPath)
            Log.i(TAG, "视频缩略图:" + media.videoThumbnailPath)
            Log.i(TAG, "原始宽高: " + media.width + "x" + media.height)
            Log.i(TAG, "裁剪宽高: " + media.cropImageWidth + "x" + media.cropImageHeight)
            Log.i(TAG, "文件大小: " + PictureFileUtils.formatAccurateUnitFileSize(media.size))
        }

        addAttachmentToFeature(result)
    }


    fun addAttachmentToFeature(list: List<LocalMedia>){
        val updateFeature = HomeFragment.updateFeature
        if(updateFeature != null){
            /**
             * 因为是更新要素，直接在这里添加进去就行了
             */
            val arcGISFeature = updateFeature as ArcGISFeature
            list.forEachIndexed { index, localMedia ->
                val realPath = localMedia.realPath
                val mimeType = localMedia.mimeType
                val fileName = localMedia.fileName
                val readBytes = File(realPath).inputStream().readBytes()
                val get = arcGISFeature.addAttachmentAsync(readBytes, mimeType, fileName).get()
            }
            val featureTable = arcGISFeature.featureTable
            val updateFeatureAsync = featureTable.updateFeatureAsync(arcGISFeature)
            if(featureTable is GeodatabaseFeatureTable){
                updateFeatureAsync.addDoneListener {
                    try {
                        val get = updateFeatureAsync.get()
                        reloadFeatureAttachmentListToAdapter()
                        showToast("添加成功")
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            }
            if(featureTable is ServiceFeatureTable){
                val applyEditsAsync = featureTable.applyEditsAsync()
                applyEditsAsync.addDoneListener {
                    try {
                        val get = applyEditsAsync.get()
                        reloadFeatureAttachmentListToAdapter()
                        showToast("添加成功")
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
            }
        } else {
            //不是更新，是添加新的feature，将结果放到主页面，等添加要素的时候再将这些附件添加进去要素里面
            HomeFragment.localMediaList.addAll(list)
            localMediaAdapter.append(list)
        }
    }

    private fun imageDialog(drawable: Drawable){
        val dialog = MaterialAlertDialogBuilder(this)
        val rootView: View = LayoutInflater.from(this).inflate(R.layout.item_img_dialog, null)
        val photoView = rootView.findViewById(R.id.photoview) as PhotoView
        photoView.enable()
        photoView.setImageDrawable(drawable)
        dialog.setView(rootView)
        val show = dialog.show()
        show.window!!.setBackgroundDrawableResource(android.R.color.transparent)
    }

    private inner class LocalMediaAdapter(data:List<LocalMedia>) : BaseRecyclerAdapter<LocalMedia>(this, data) {
        override fun getItemLayoutId(viewType: Int): Int {
            return R.layout.item_picture
        }

        override fun bindData(holder: RecyclerViewHolder, position: Int, item: LocalMedia) {
            val myWidth = QMUIDisplayHelper.getScreenWidth(this@AttachmentActivity) / 4
            holder.getView(R.id.imageView).apply {
                layoutParams.apply {
                    width = myWidth
                    height = myWidth
                }
            }

            holder.getTextView(R.id.imageName).text = item.fileName

            val drawable = Drawable.createFromPath(item.realPath)
            holder.itemView.setOnClickListener {
                imageDialog(drawable!!)
            }
            holder.getImageView(R.id.imageView).setImageDrawable(drawable)
            holder.getView(R.id.progressBar).visibility = View.GONE

            holder.getView(R.id.delete).let {
                it.setOnClickListener {
                    remove(holder.absoluteAdapterPosition)
                    //是新增照片，就不弹窗了直接从list移除，反复弹窗对用户体验不好
                    HomeFragment.localMediaList.remove(item)
                }
            }

        }

    }

    private inner class AttachmentAdapter(data:List<Attachment>) : BaseRecyclerAdapter<Attachment>(this, data) {
        override fun getItemLayoutId(viewType: Int): Int {
            return R.layout.item_picture
        }

        override fun bindData(holder: RecyclerViewHolder, position: Int, item: Attachment) {
            val myWidth = QMUIDisplayHelper.getScreenWidth(this@AttachmentActivity) / 4
            holder.getView(R.id.imageView).apply {
                layoutParams.apply {
                    width = myWidth
                    height = myWidth
                }
            }

            holder.getTextView(R.id.imageName).text = item.name

            val fetchDataAsync = item.fetchDataAsync()
            fetchDataAsync.addDoneListener {
                try {
                    val fileName = item.name
                    val inputStream = fetchDataAsync.get()
                    val drawable = Drawable.createFromStream(inputStream, fileName)
                    holder.itemView.setOnClickListener {
                        if(fileName.endsWith("png") || fileName.endsWith("jpg")){
                            imageDialog(drawable!!)
                        } else {
                            showToast("你自行去拓展，我只帮你显示图片")
                        }
                    }
                    holder.getImageView(R.id.imageView).setImageDrawable(drawable)
                    holder.getView(R.id.progressBar).visibility = View.GONE
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }

            holder.getView(R.id.delete).let {
                it.setOnClickListener {
                    MaterialAlertDialogBuilder(this@AttachmentActivity)
                        .setTitle("提示")
                        .setMessage("确定删除该附件吗？")
                        .setNegativeButton("取消",null)
                        .setPositiveButton("确定") { dialog, which ->
                            remove(holder.absoluteAdapterPosition)

                            //既然是attachmentAdapter了，那homeFragment中的feature肯定不为null了
                            val deleteAttachmentAsync = (HomeFragment.updateFeature as ArcGISFeature).deleteAttachmentAsync(item)
                            deleteAttachmentAsync.addDoneListener {
                                try {
                                    val get = deleteAttachmentAsync.get()
                                    showToast("删除成功")
                                } catch (e: Exception) {
                                    e.printStackTrace()
                                }
                            }


                        }.show()
                }
            }

        }

    }
}